package msigraphx.gibbsSampler;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class VarDistr<Type> implements Cloneable {
	private Map<RandomVariableValue<Type>, Float> val;
	private boolean isDenormalized;

	public VarDistr() {
		super();
		this.val = new HashMap<RandomVariableValue<Type>, Float>();
		this.isDenormalized = true;
	}
	
	public VarDistr(Map<RandomVariableValue<Type>, Float> val) {
		super();
		this.val = val;
		this.isDenormalized = false;
	}
	
	public RandomVariableValue<Type> drawUniformlyFromDistr() {
		Random rand = new Random();
		float randVal = rand.nextFloat();
		float sum = 0;
		for(Map.Entry<RandomVariableValue<Type>, Float> entry : val.entrySet()) {
			sum += entry.getValue();
			if(sum < 0 || sum > 1) {
				throw new IllegalStateException("probability not in [0,1]  sum ="+sum);
			}
			if(randVal<=sum) {
				return entry.getKey();
			}
		}
		throw new IllegalStateException("variable value not selected  map.size() = "+val.size());
	}
	
	public void addValue(RandomVariableValue<Type> varVal, Float prob) {
		val.put(varVal,prob);
	}
	
	public boolean containsVarValue(RandomVariableValue<Type> varVal) {
		return val.containsKey(varVal);
	}
	
	public void incValue(RandomVariableValue<Type> varVal) {
		val.put(varVal, val.get(varVal)+1f);
	}
	
	public void normalize() {
		if(isDenormalized) {
			float sum = 0f;
			for(Map.Entry<RandomVariableValue<Type>, Float> entry: val.entrySet()) {
				sum += entry.getValue();
			}
			for(RandomVariableValue<Type> varVal: val.keySet()) {
				val.put(varVal, val.get(varVal)/sum);
			}
			isDenormalized = true;
		}
	}
	
	public Float getProb(RandomVariableValue<Type> value) {
		return val.get(value);
	}
	
	public String toString() {
		return val.toString();
	}
}